<template>
	<view v-if="currentShow" :class="['v-loading', { 'v-loading--full-screen': fullScreen }]" :style="loadingStyle">
		<slot name="spinner">
			<view class="v-loading-spinner">
				<view class="spinner-outer"></view>
				<view class="spinner-inner"></view>
			</view>
		</slot>
		<text v-if="text" class="v-loading-text">{{ text }}</text>
	</view>
</template>

<script setup lang="ts">
import { computed, ref, watch,onMounted,inject } from 'vue';

const props = defineProps({
	fullScreen: {
		type: Boolean,
		default: false
	},
	text: {
		type: String,
		default: '',
		required: true
	},
	size: {
		type: String,
		default: 'medium',
		validator: (value: any) => {
			return ['small', 'medium', 'large'].includes(value);
		}
	},
	color: {
		type: String,
		default: '#287afa'
	},
	textColor: {
		type: String,
		default: '#666'
	},
	duration: {
		type: Number,
		default: 0
	},
	show: {
		type: Boolean,
		default: false
	}
});

const emit = defineEmits(['update:show']);

const config = inject<any>('config');
const currentShow = ref(props.show);
let timer: NodeJS.Timeout | null = null;

watch(
	() => props.show,
	(newValue) => {
		currentShow.value = newValue;
		if (newValue) {
			if (timer) {
				clearTimeout(timer);
			}
			if (props.duration > 0) {
				timer = setTimeout(() => {
					currentShow.value = false;
					emit('update:show', false);
				}, props.duration);
			}
		}
	}
);

watch(
	() => props.duration,
	(newValue) => {
		if (currentShow.value && newValue > 0) {
			if (timer) {
				clearTimeout(timer);
			}
			timer = setTimeout(() => {
				currentShow.value = false;
				emit('update:show', false);
			}, newValue);
		}
	}
);

onMounted(()=>{
	if (currentShow.value &&  props.duration > 0) {
		if (timer) {
			clearTimeout(timer);
		}
		timer = setTimeout(() => {
			currentShow.value = false;
			emit('update:show', false);
		},  props.duration);
	}
})

const loadingStyle = computed(() => {
	return {
		'--loading-color': props.color,
		'--text-color': props.textColor
	};
});
</script>

<style lang="scss" scoped>
.v-loading {
	min-height: 150rpx;
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 16rpx;
	z-index: 1000;

	&--full-screen {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background-color: rgba(255, 255, 255, 0.8);
	}

	.v-loading-spinner {
		width: 80rpx;
		height: 80rpx;
		position: relative;
		margin-bottom: 12rpx;
	}

	.spinner-outer {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		border: 6rpx solid var(--loading-color);
		border-radius: 50%;
		border-top-color: transparent;
		animation: spin 1s linear infinite;
	}

	.spinner-inner {
		position: absolute;
		top: 20%;
		left: 20%;
		transform: translate(-50%, -50%);
		width: 60%;
		height: 60%;
		border: 6rpx solid var(--loading-color);
		border-radius: 50%;
		border-top-color: transparent;
		animation: spin 0.6s linear infinite reverse;
	}

	.v-loading-text {
		color: var(--text-color);
		font-size: v-bind("config.fontSize.mediumText");
	}

	@keyframes spin {
		0% {
			transform: rotate(0deg);
		}
		100% {
			transform: rotate(360deg);
		}
	}

	&--small .v-loading-spinner {
		width: 60rpx;
		height: 60rpx;
	}

	&--small .spinner-outer {
		border-width: 4rpx;
	}

	&--small .spinner-inner {
		width: 70%;
		height: 70%;
		border-width: 4rpx;
	}

	&--large .v-loading-spinner {
		width: 100rpx;
		height: 100rpx;
	}

	&--large .spinner-outer {
		border-width: 8rpx;
	}

	&--large .spinner-inner {
		width: 50%;
		height: 50%;
		border-width: 8rpx;
	}
}
</style>